/*
 * PhotonRTOS础光实时操作系统 -- AUTOSAR钩子内部实现
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef OS_HOOKS_INTERNAL_H
#define OS_HOOKS_INTERNAL_H

#include <autosar/hooks.h>
#include <photon/types.h>
#include <autosar/calllevel_internal.h>

extern VAR(uintptr_t, AUTOMATIC) osek_hook_error_code;
extern VAR(uintptr_t, AUTOMATIC) osek_hook_param1;
extern VAR(uintptr_t, AUTOMATIC) osek_hook_param2;
extern VAR(uintptr_t, AUTOMATIC) osek_hook_param3;

#if defined(CONFIG_OSEK_HOOK_ERROR)

extern VAR(int32_t, AUTOMATIC) osek_hook_running;
LOCAL_INLINE FUNC(int32_t, OS_CODE) osek_in_hook(void)
{
	return osek_hook_running;
}

extern FUNC(void, OS_CODE) osek_call_hook(void);

/**
 * 处理错误钩子，不包含任何参数
 */
#define osek_call_hook_0(service_id, ret) \
	do {								\
		VAR(uintptr_t, AUTOMATIC) flags;					\
									\
		local_irq_save(flags);					\
		if (!osek_in_hook())	{				\
			osek_hook_service_id = OSServiceId_##service_id;\
			osek_hook_error_code = (uintptr_t)ret;	\
			CONTEXT_MARK_START(ENV_ERROR_HOOK) \
			osek_call_hook();				\
			CONTEXT_MARK_END	\
		}							\
		local_irq_restore(flags);				\
	} while (0)

/**
 * 处理错误钩子，包含一个参数
 */
#define osek_call_hook_1(service_id, ret, param1) \
	do {								\
		VAR(uintptr_t, AUTOMATIC) flags;					\
									\
		local_irq_save(flags);					\
		if (!osek_in_hook())	{				\
			osek_hook_service_id = OSServiceId_##service_id;\
			osek_hook_error_code = (uintptr_t)ret;	\
			osek_hook_param1 = (uintptr_t)param1;	\
			CONTEXT_MARK_START(ENV_ERROR_HOOK) \
			osek_call_hook();				\
			CONTEXT_MARK_END				\
		}							\
		local_irq_restore(flags);				\
	} while (0)

/**
 * 处理错误钩子，包含两个参数
 */
#define osek_call_hook_2(service_id, ret, param1, param2) \
	do {								\
		VAR(uintptr_t, AUTOMATIC) flags;					\
									\
		local_irq_save(flags);					\
		if (!osek_in_hook())	{				\
			osek_hook_service_id = OSServiceId_##service_id;\
			osek_hook_error_code = (uintptr_t)ret;	\
			osek_hook_param1 = (uintptr_t)param1;	\
			osek_hook_param2 = (uintptr_t)param2;	\
			CONTEXT_MARK_START(ENV_ERROR_HOOK) \
			osek_call_hook();				\
			CONTEXT_MARK_END					\
		}							\
		local_irq_restore(flags);				\
	} while (0)

/**
 * 处理错误钩子，包含三个参数
 */
#define osek_call_hook_3(service_id, ret, param1, param2, param3) \
	do {								\
		VAR(uintptr_t, AUTOMATIC) flags;					\
									\
		local_irq_save(flags);					\
		if (!osek_in_hook())	{				\
			osek_hook_service_id = OSServiceId_##service_id;\
			osek_hook_error_code = (uintptr_t)ret;	\
			osek_hook_param1 = (uintptr_t)param1;	\
			osek_hook_param2 = (uintptr_t)param2;	\
			osek_hook_param3 = (uintptr_t)param3;	\
			CONTEXT_MARK_START(ENV_ERROR_HOOK) \
			osek_call_hook();				\
			CONTEXT_MARK_END	\
		}							\
		local_irq_restore(flags);				\
	} while (0)
#else
#define osek_call_hook_0(service_id, ret)
#define osek_call_hook_1(service_id, ret, param1)
#define osek_call_hook_2(service_id, ret, param1, param2)
#define osek_call_hook_3(service_id, ret, param1, param2, param3)
#endif /* CONFIG_OSEK_HOOK_ERROR */

#endif /* OS_HOOKS_INTERNAL_H */
